package com.liu.user.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liu.user.entity.base.UserBasicsInfo;
import com.liu.user.entity.base.UserPasswordInfo;
import com.liu.user.entity.dto.UserLoginInfoVO;
import com.liu.user.entity.dto.UserPermissionInfoDTO;
import com.liu.user.entity.qo.UserLoginQO;
import com.liu.user.mapper.UserBasicsInfoMapper;
import com.liu.user.service.IUserBasicsInfoService;
import com.liu.user.service.IUserPasswordInfoService;
import com.liu.user.service.IUserPermissionInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import utils.RandomPersonInfoUtil;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 用户基础信息表 服务实现类
 * </p>
 *
 * @author LiuChengLong
 * @since 2022-09-07
 */
@Service
@Slf4j
public class UserBasicsInfoServiceImpl extends ServiceImpl<UserBasicsInfoMapper, UserBasicsInfo> implements IUserBasicsInfoService {

    @Resource
    private IUserPasswordInfoService userPasswordInfoService;

    @Resource
    private IUserPermissionInfoService userPermissionInfoService;

    /**
     * 公钥
     */
    private String privateKey = "";

    /**
     * 私钥
     */
    private String publicKey = "";

    private final HashMap<Boolean, String> msgResult = new HashMap<>();

    /**
     * 注册
     * @param userBasicsInfo 用户注册信息
     * @return 注册结果
     */
    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public String register(UserBasicsInfo userBasicsInfo){
        // 获取账户的公钥和密钥
        this.getPrivateKeyAndPublicKey();
        // 将用户输入的密码进行加密
        userBasicsInfo.setPassword(SaSecureUtil.rsaEncryptByPublic(publicKey, userBasicsInfo.getPassword()));
        // 生成每个用户特有的账号
        userBasicsInfo.setAccountNumber(DateUtil.year(DateUtil.date()) + RandomPersonInfoUtil.getRandomNumBySize(4));
        // 初始化用户金币、血量
        userBasicsInfo.setGameMoney(100);
        userBasicsInfo.setMaxHP(100);
        userBasicsInfo.setNowHP(100);
        // 保存用户信息
        boolean saveBasicsInfo = super.save(userBasicsInfo);
        UserPasswordInfo userPasswordInfo = new UserPasswordInfo();
        userPasswordInfo.setUserId(baseMapper.getUserId(userBasicsInfo));
        userPasswordInfo.setPrivateKey(privateKey);
        userPasswordInfo.setPublicKey(publicKey);
        // 保存用户密码公钥和私钥
        boolean savePasswordInfo = userPasswordInfoService.save(userPasswordInfo);
        if (saveBasicsInfo && savePasswordInfo) {
            return "注册成功！";
        } else {
            throw new RuntimeException("注册失败！");
        }
    }

    /**
     * 登录
     * @param userLoginQO 登录信息
     * @return 用户信息
     */
    @Override
    public UserLoginInfoVO login(UserLoginQO userLoginQO) {
        // 使用用户名、账号、手机号、邮箱查询用户信息
        UserLoginInfoVO userLoginInfo = baseMapper.getUserLoginInfo(userLoginQO);
        String decryptPassword = null;
        if (userLoginInfo != null){
            // 将数据库的密码解密
            decryptPassword = SaSecureUtil.rsaDecryptByPrivate(userLoginInfo.getPrivateKey(), userLoginInfo.getPassword());
        }
        // 如果密码一样登录成功(Sa-Token登录)
        if (userLoginQO.getPassword().equals(decryptPassword)){
            StpUtil.login(userLoginInfo.getUserId());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            userLoginInfo.setSaTokenInfo(tokenInfo);
            userLoginInfo.setPrivateKey(null);
            // 获取用户所有权限
            List<UserPermissionInfoDTO> userPermission = userPermissionInfoService.getUserPermission(String.valueOf(userLoginInfo.getUserId()));
            userLoginInfo.setUserPermissionInfoList(userPermission);
            // 更新用户最后登录时间
            UpdateWrapper<UserBasicsInfo> userBasicsInfoUpdateWrapper = new UpdateWrapper<>();
            userBasicsInfoUpdateWrapper.eq("id", userLoginInfo.getUserId());
            userBasicsInfoUpdateWrapper.set("last_login_time", DateUtil.now());
            super.update(userBasicsInfoUpdateWrapper);
        }
        return userLoginInfo;
    }

    /**
     * 获取用户私钥和密钥
     */
    public void getPrivateKeyAndPublicKey(){
        try {
            HashMap<String, String> stringStringHashMap = SaSecureUtil.rsaGenerateKeyPair();
            privateKey = stringStringHashMap.get("private");
            publicKey = stringStringHashMap.get("public");
        } catch (Exception e) {
            log.error("获取用户私钥、密钥失败");
            e.printStackTrace();
        }
    }

}
